package worker.model.service;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;

import worker.model.dao.HistoryDao;
import worker.model.dao.ProcessDao;
import worker.model.dao.WipDao;
import worker.model.dao.WorkOrderDao;
import worker.model.vo.DefectsVO;
import worker.model.vo.HistoryVO;
import worker.model.vo.ItemInfoVO;
import worker.model.vo.ListVO;
import worker.model.vo.MemberVO;
import worker.model.vo.OperationsVO;
import worker.model.vo.PagingBean;
import worker.model.vo.RealTimeInfoVO;
import worker.model.vo.SearchConditionVO;
import worker.model.vo.WipVO;
import worker.model.vo.WorkOrdersVO;

public class ProcessService {
	private ProcessDao processDao;
	private WorkOrderDao workOrderDao;
	private WipDao wipDao;
	private HistoryDao hisDao;

	public ProcessService(ProcessDao processDao, WorkOrderDao workOrderDao,
			WipDao wipDao,HistoryDao hisDao) {
		super();
		this.processDao = processDao;
		this.workOrderDao = workOrderDao;
		this.wipDao = wipDao;
		this.hisDao = hisDao;
	}

	/**
	 * 결함 만드는 함수
	 */
	public HashMap makeDefect(int quantity, String serial_no_start) {
		Random random = new Random();
		HashMap map = new HashMap();
		// 결함이 발생할 수 있는 최대 경우의 수
		int max = (int) Math.ceil(quantity * 0.01) + 3;  //수정할것
		// 결함의 수 : 0~max 중 하나를 random으로 뽑는다.
		int defects = random.nextInt(max)+1;
		// - 시작값
		int start = Integer.parseInt(serial_no_start);
		// 결함이 발생한 번호를 저장할 배열
		int[] result = new int[defects];
		int[] op = new int[defects];
		// 결함번호 추출하기
		for (int i = 0; i < defects; i++) {
			result[i] = random.nextInt(quantity) + start;
			for (int j = 0; j < i; j++) {
				if (result[j] == result[i]) {
					result[j] = random.nextInt(quantity) + start;
					j = 0;
				}
			}
		}// for
		for(int i=0;i<defects;i++){
			op[i] = random.nextInt(4)+1;
		}
		String[] operation = new String[defects];
		for(int i=0;i<defects;i++){
			operation[i] = Integer.toString(op[i]);
		}
		for(int i=0;i<defects;i++){
			map.put(operation[i], Integer.toString(result[i]));
		}
		return map;
	}

	/**
	 * work_order list를 불러오는 service
	 */
	public ArrayList<HashMap> getWorkOrderList() {
		ArrayList<HashMap> list = null;
		try {
			list = workOrderDao.getWorkOrderList();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return list;
	}

	/**
	 * WO에 해당하는 주문량(남아있는)
	 */
	public int getWoQty(String wo) {
		int qty = 0;
		try {
			ArrayList<HashMap> list = workOrderDao.getSerialStartMaxNoByWO(wo);
			int serial_no_start = Integer.parseInt((String) list.get(0).get(
					"SERIAL_NO_START"));
			int serial_no_max = Integer.parseInt((String) list.get(0).get(
					"SERIAL_NO_MAX"));
			qty = serial_no_max - serial_no_start + 1;
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return qty;
	}

	/**
	 * operation ->정상 수행 된 item
	 */
	public void operationSuccess(WorkOrdersVO woVO, String operation_id,
			String mem_id, String serial_no) {
		boolean flag=false;
		try {
			String next_operation_id = null;
			String defect_id = "PASS";
			if(operation_id.equals("OPICE")){
				next_operation_id="OPRB";
				flag=true;
			} else if (operation_id.equals("OPRB")) {
				next_operation_id = "OPTP";
			} else if (operation_id.equals("OPTP")) {
				next_operation_id = "OPPCK";
			} else if (operation_id.equals("OPPCK")) {
				next_operation_id = "COMPLETE";
			} 
			WipVO wip = new WipVO(defect_id, operation_id, next_operation_id,
					serial_no);
			HistoryVO hisVO = new HistoryVO(new MemberVO(mem_id),
					new OperationsVO(operation_id), new DefectsVO(defect_id),
					new WorkOrdersVO(woVO.getWork_order_id()), 1, serial_no);
			if(flag){
				processDao.insertWip(wip);
				flag=false;
			}else{
				processDao.updateWip(wip);
			}			
			processDao.insertHistory(hisVO);
		} catch (SQLException e1) {
			e1.printStackTrace();
		} 
	}
	/**
	 * operation ->defect item
	 */
	public void operationDefect(WorkOrdersVO woVO,String operation_id,
			String mem_id, String serial_no,String defect_id){
		//System.out.println("결함 시리얼넘버 catch!!:" + serial_no);
		WipVO wip = new WipVO(defect_id, operation_id, "",serial_no);
		try {
			Object flag = processDao.isExistErrorInWip(wip); //이미 존재하는 결함이면
			if(flag!=null){
				//System.out.println("이미 존재하니까 update 안함");
			}else{			
				HistoryVO hisVO = new HistoryVO(new MemberVO(mem_id),
						new OperationsVO(operation_id), new DefectsVO(defect_id),
						new WorkOrdersVO(woVO.getWork_order_id()), 1, serial_no);
				processDao.insertWip(wip);
				processDao.insertHistory(hisVO);
			}			
		} catch (SQLException e) {
			e.printStackTrace();
		}		
	}
	/**
	 * operation 공정시작
	 */
	public void operation(WorkOrdersVO woVO, String mem_id) {
		String complete = "N";				
		try {			
			ArrayList<HashMap> list = workOrderDao.getSerialStartMaxNoByWO(woVO	.getWork_order_id());
			String serial_no_max = (list.get(0).get("SERIAL_NO_MAX")).toString();
			String serial_no_start = (list.get(0).get("SERIAL_NO_START")).toString();
			HistoryVO hisVO = new HistoryVO(new MemberVO(mem_id), new OperationsVO("START"), new DefectsVO("DEFAULT"), woVO,woVO.getQuantity(), serial_no_start);
			processDao.insertHistory(hisVO); //공정이 시작 되었음을 DB에 등록
			int s = Integer.parseInt(serial_no_start);
			int total = woVO.getQuantity(); // 만들 총 수량
			String max = Integer.toString(s + total - 1);
			int e = Integer.parseInt(max);
			
			HashMap defect_serial_id = makeDefect(total,serial_no_start); // 결함번호 받아오기
			//System.out.println("만든 결함변호 : " + defect_serial_id);
			ArrayList<String> serial_no_list = new ArrayList(); // start_no~max_no															

			for (int h = s; h <= e; h++) { // s부터 e까지 serial_no_list에 추가한다.
				serial_no_list.add(Integer.toString(h));
			}
			//System.out.println("serial_no_list : " + serial_no_list);

			String num = null;
			boolean flag1 = true;boolean flag2 = true;boolean flag3 = true;boolean flag4 = true;
			int i = 0;		int j = 0;
			int count1 = 0;	int count2 = 0;	int count3 = 0;	int count4 = 0; // 총 4번의 공정
			for (int h = 0; h < total + 3; h++) {
				Thread.sleep(800);
				if (i >= 3 && j <= total) { // OPPCK
					num = serial_no_list.get(count4++);
					if(defect_serial_id.containsKey("4") && defect_serial_id.get("4").equals(num)){
						System.out.println("공정4단계 에러 catch : "+num);
						this.operationDefect(woVO,"OPPCK",mem_id,num,"DFP");							
						flag4=false;
					}				
					for(int index=1;index<4;index++){
						String key = Integer.toString(index);
						if(defect_serial_id.containsKey(key) &&defect_serial_id.get(key).equals(num)){
							flag4=false;
						}
					}
					if(flag4){
						this.operationSuccess(woVO, "OPPCK", mem_id, num);
						//System.out.println("4공정SN : " + num);
					}
					j++;
					flag4=true;
				} //OPPCK close
			if (i >= 2 && j <= total - 1) { // OPTP
				//System.out.println("3공정 ");
				num = serial_no_list.get(count3++);
				if(defect_serial_id.containsKey("3") && defect_serial_id.get("3").equals(num)){
					System.out.println("공정3단계에러catch : "+num);
					this.operationDefect(woVO,"OPTP",mem_id,num,"DFW");							
					flag3=false;
				}				
				for(int index=1;index<3;index++){
					String key = Integer.toString(index);
					if(defect_serial_id.containsKey(key) &&defect_serial_id.get(key).equals(num)){
						//System.out.println("겹치므로 defect제외3"+num);
						flag3=false;
					}
				}
				if(flag3){
					this.operationSuccess(woVO, "OPTP", mem_id, num);
					//System.out.println("3공정SN : " + num);
				}	
				flag3=true;
			} //OPTP close
			if (i >= 1 && j <= total - 2) { // OPRB
				//System.out.println("2공정 flag : "+flag2);
				num = serial_no_list.get(count2++);
				if(defect_serial_id.containsKey("2") && defect_serial_id.get("2").equals(num)){
						System.out.println("공정2단계에러catch : "+num);
						this.operationDefect(woVO,"OPRB",mem_id,num,"DFW");							
						flag2=false;
				}	
				
				for(int index=1;index<2;index++){
					String key = Integer.toString(index);
					if(defect_serial_id.containsKey(key) &&defect_serial_id.get(key).equals(num)){
						//System.out.println("겹치므로 defect제외2"+num);
						flag2=false;						
					}
				}
				System.out.println("flag2:"+flag2);
				if(flag2){
					this.operationSuccess(woVO, "OPRB", mem_id, num);
					//System.out.println("2공정 SN : " + num);
				}	
				flag2=true;
			}
			if (i >= 0 && j <= total - 3) { // OPICE
				num = serial_no_list.get(count1++);
				if(defect_serial_id.containsKey("1") && defect_serial_id.get("1").equals(num)){
						System.out.println("공정1단계에러catch : "+num);
						this.operationDefect(woVO,"OPICE",mem_id,num,"DFW");							
						flag1 = false;
					}	
				if(flag1){
					this.operationSuccess(woVO, "OPICE", mem_id, num);
					//System.out.println("1공정 SN : " + num);						
				}
				i++;	flag1=true;				
			}	
			}
			 //history 등록하는 for
			//workorder update
			if (serial_no_max.equals(max)) {
				complete = "Y";
			}
			serial_no_start = Integer.toString(e + 1);
			workOrderDao.updateWorkOrder(new WorkOrdersVO(woVO.getWork_order_id(), serial_no_start, complete));
			
			String comp = processDao.getCompleteWorkOrder(woVO.getWork_order_id()); 
			int qty = processDao.getCompleteQtyInWip(); 
			hisVO.setOperationsVO(new OperationsVO("COMPLETE"));
			hisVO.setQuantity(qty);
			
			if(comp.equals("Y")){
				processDao.insertHistory(hisVO); 
			}else{
				hisVO.setOperationsVO(new OperationsVO("END"));
				processDao.insertHistory(hisVO); 
			}
			processDao.deleteWip();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	/**
	 * 실시간 화면 업데이트
	 * op1 : 성공량, 실패량, defect 번호
	 * op2 : 성공량, 실패량, defect 번호 
	 * op3 : 성공량, 실패량, defect 번호
	 * op4 : 성공량, 실패량, defect 번호
	 */
	public ArrayList<RealTimeInfoVO> realTimeUpdate(WorkOrdersVO woVO,String mem_id) {
		ArrayList<RealTimeInfoVO> real_info=null;
		try {
			Thread.sleep(1000);
			String serial_no_start = woVO.getSerial_no_start();
			int s = Integer.parseInt(serial_no_start);
			int total = woVO.getQuantity(); // 만들 총 수량
			String serial_no_max = Integer.toString(s + total - 1);
			int e = Integer.parseInt(serial_no_max);
			SearchConditionVO vo = new SearchConditionVO(woVO.getWork_order_id(),mem_id,serial_no_start,serial_no_max);
			
			int success1 = processDao.getOP1SuccessInfoInHistory(vo);
			int fail1 = processDao.getOP1FailInfoInHistory(vo);
			ArrayList<String> list1 = processDao.getOP1FailSerialNo(vo);
			
			int success2 = processDao.getOP2SuccessInfoInHistory(vo);
			int fail2 = processDao.getOP2FailInfoInHistory(vo);
			ArrayList<String> list2 = processDao.getOP2FailId(vo);
			if(list2==null){
				list2 = new ArrayList<String>();list2.add("dont search");
			}
			int success3 = processDao.getOP3SuccessInfoInHistory(vo);
			int fail3 = processDao.getOP3FailInfoInHistory(vo);
			ArrayList<String> list3 = processDao.getOP3FailId(vo);
			
			int success4 = processDao.getOP4SuccessInfoInHistory(vo);
			int fail4= processDao.getOP4FailInfoInHistory(vo);
			ArrayList<String> list4 = processDao.getOP4FailId(vo);
			
			real_info = new ArrayList<RealTimeInfoVO>();
			real_info.add(new RealTimeInfoVO(success1,fail1,list1));
			real_info.add(new RealTimeInfoVO(success2,fail2,list2));
			real_info.add(new RealTimeInfoVO(success3,fail3,list3));
			real_info.add(new RealTimeInfoVO(success4,fail4,list4));
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return real_info;		
	}
	/**
	 * 시작번호 받아오기
	 */
	public String getStartNo(String wO) {
		String start_no=null;
		try {
			start_no= processDao.getStartNo(wO);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return start_no;
	}
	 public void updateItemByQuantity(int quantity) {
		  // 재고업데이트. 빙수 1개  -> 얼음 300 , 팥->200,토핑->50
		  int ice=quantity*3;
		  int rb=quantity*2;
		  int tp= (int) Math.ceil(0.5*quantity); // 소수점 이하 무조건 올림
		  int pc=quantity*1;
		  
		  ItemInfoVO  iivo1= new ItemInfoVO("ICE",ice);
		  ItemInfoVO  iivo2= new ItemInfoVO("PC",pc);
		  ItemInfoVO  iivo3= new ItemInfoVO("RB",rb);
		  ItemInfoVO  iivo4= new ItemInfoVO("TP", tp);
		  System.out.println("");System.out.println("");
		  System.out.println(ice+" "+rb+" "+" "+tp+" "+pc);
		  
		  try {
		   this.processDao.updateMaterial(iivo1);
		   this.processDao.updateMaterial(iivo2);
		   this.processDao.updateMaterial(iivo3);
		   this.processDao.updateMaterial(iivo4);
		  } catch (SQLException e) {
		     e.printStackTrace();
		  }
		 }
	 /**
	  * 트래킹
	  */
	public ListVO trackingSN(HashMap map) {
		int total=1;
		int pageNo=1;
		PagingBean paging=new PagingBean(total,pageNo);
		ListVO lvo=null;
		try {
			lvo = new ListVO(hisDao.getSerialList(map),paging);
			System.out.println("service:"+lvo);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return lvo;
	} 
}
